﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;
using Microsoft.Win32;
using Cqrs.StateMachineDesigner.CustomCode;
using Cqrs.CodeGeneration.CSharp;
using Cqrs.Common;
using Cqrs.StateMachineDesigner.Resources;

namespace Cqrs.StateMachineDesigner.Generator
{
    /// <summary>
    /// Interaction logic for CodeGenerator.xaml
    /// </summary>
    public partial class CodeGenerator : Window
    {
        private string _namespace;
        private string _domainName;
        private IList<DomainProperty> _domainProperties;
        private StateMachine _stateMachine;
        private List<CommandEvent> _adHocMethods;
        private string _smfFile;

        public CodeGenerator()
        {
            InitializeComponent();
        }

        public void ShowForm(
            StateMachine stateMachine,
            string domainNamespace,
            string domainName,
            IList<DomainProperty> domainProperties,
            List<CommandEvent> adHocMethods,
            string smfFile)
        {
            _stateMachine = stateMachine;
            _namespace = domainNamespace;
            _domainName = domainName;
            _domainProperties = domainProperties;
            _smfFile = smfFile;
            _adHocMethods = adHocMethods;

            var commandsEvents = _stateMachine.UniqueCommandEventList;
            commandsEvents.AddRange(adHocMethods);

            grdEvents.DataContext = commandsEvents;
            grdEvents.CanUserAddRows = false;
            dgStates.DataContext = _stateMachine.States.Select(p => new { State = p });
            dgStates.CanUserAddRows = false;
            
            if (_stateMachine.InitialState == null)
            {
                MessageBox.Show("A Start State is required for Code Generation.");
                return;
            }

            Generate();
            this.ShowDialog();
        }

        private void Generate()
        {

            txtEvents.Text = "";

            GeneratorModelBase generatorModel = new CSharpGenerator(
                                _stateMachine, _adHocMethods,
                                _namespace, _domainName,
                                _domainProperties, _smfFile);

            if (_stateMachine.Any() && generatorModel.CommandEventList.Any())
            {
                txtEvents.Text = generatorModel.EventCode;
                txtDomain.Text = generatorModel.DomainCode;
                txtCommands.Text = generatorModel.CommandCode;
                txtCommandsHandlers.Text = generatorModel.CommandHandlerCode;
                txtIntegrationTests.Text = generatorModel.TestCode;
            }
        }

        private void btnGenerate_Click(object sender, RoutedEventArgs e)
        {
            try
            {

                SaveFileDialog saveFile = new SaveFileDialog();
                saveFile.Filter = "C# Files (*.cs)|*.cs";
                saveFile.FileName = _domainName + ".generated.cs";
                if (saveFile.ShowDialog().Value == true)
                {
                    var fileStream = System.IO.File.CreateText(saveFile.FileName);

                    fileStream.WriteLine(string.Format(StringResources.CodeGenHeader, DateTime.Now));

                    if (string.IsNullOrEmpty(_namespace))
                    {
                        fileStream.Write("namespace {0}", _namespace);
                        fileStream.Write("{");
                    }

                    if (chkDomain.IsChecked.Value) fileStream.Write(txtDomain.Text);
                    if (chkEvents.IsChecked.Value) fileStream.Write(txtEvents.Text);
                    if (chkCommands.IsChecked.Value) fileStream.Write(txtCommands.Text);
                    if (chkCommandHandlers.IsChecked.Value) fileStream.Write(txtCommandsHandlers.Text);
                    if (chkIntegrationTests.IsChecked.Value) fileStream.Write(txtIntegrationTests.Text);

                    if (string.IsNullOrEmpty(_namespace))
                    {
                        fileStream.Write("}");
                    }
                    fileStream.Close();
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private string GetTransitionTour()
        {
            StringBuilder sb = new StringBuilder();
            int index = 1;
            foreach (var tour in _stateMachine.TransitionTourSequence())
            {
                sb.AppendLine(string.Format("Sequence {0}:", index++));
                foreach (var sequence in tour)
                {
                    sb.AppendLine(sequence.ToString());
                    sb.AppendLine("---------------");
                }
            }
            return sb.ToString();
        }
    }
}
